// 完成异步日志工作器
#ifndef LOOPER_HPP
#define LOOPER_HPP
#include "buffer.hpp"
#include <mutex>
#include <memory>
#include <condition_variable>
#include <thread>
#include <functional>
#include <atomic>
namespace blog
{

    enum class looper_type
    {
        SAFE_TYPE,
        UNSAFE_TYPE
    };
    class looper
    {
    public:
        using func = std::function<void(buffer &)>;
        using ptr = std::shared_ptr<looper>;
    public:
        looper(const func &cb, looper_type lt = looper_type::SAFE_TYPE) : _thread(std::thread(&looper::entryFunc, this)),
                                                                          _stop(false),
                                                                          _cb(cb),
                                                                          _lt(lt) {}
        ~looper() { stop(); }
        void stop()
        {
            _stop = true;
            _con_cond.notify_all();
            _thread.join();
        }
        void push(const char *data, size_t len)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            if (_lt == looper_type::SAFE_TYPE) // 安全模式下判断容量是否足够 如果不足就会等待空间足够再运行
                _pro_cond.wait(lock, [&]()
                               { return _pro_buffer.writterAble_len() >= len; });
            _pro_buffer.push(data, len);
            _con_cond.notify_all();
        }

    private:
        void entryFunc()
        {

            while (1)
            {
                {
                    std::unique_lock<std::mutex> lock(_mutex);
                    if(_stop&&_pro_buffer.empty())  break;//确保进程关闭的时候 将缓冲区的数据写完再退
                    _con_cond.wait(lock, [&]()
                                   { return _stop || !_pro_buffer.empty(); });
                    _con_buffer.swap(_pro_buffer);     // 交换缓冲区数据
                    if (_lt == looper_type::SAFE_TYPE) // 安全状态才需要唤醒,不然不会陷入阻塞
                        _pro_cond.notify_all();        // 唤醒生产者
                }
            
            _cb(_con_buffer);    // 调用回调函数处理消费缓冲区
            _con_buffer.reset(); // 使用完成后清空缓冲区
            }
        }

    private:
        looper_type _lt;
        std::atomic<bool> _stop; // 设成原子的 简单操作时不用上锁了
        buffer _pro_buffer;      // 生产缓冲区
        buffer _con_buffer;      // 消费缓冲区
        std::mutex _mutex;
        std::thread _thread;
        std::condition_variable _pro_cond; // 生产者
        std::condition_variable _con_cond; // 消费者
        func _cb;                          // 由外部传入的处理消费缓冲区的方法
    };
}

#endif